﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace PokeTD
{
    class HighscoreScreen : GameScreen
    {
        ContentManager content;

        Texture2D backgroundTexture;
        Texture2D backgroundLayer;
        SpriteFont font;
        SpriteFont smallfont;

        InputAction inputExit;
        InputAction scrollUp;
        InputAction scrollDown;

        HighscoreEntry[] AllData;
        HighscoreEntry[] Data;
        string[] Maps;
        string chosenMap = "TestmapSmall";

        Dictionary<int, Texture2D> AvatarCache;

        Texture2D ScrollButtonLeft;
        Texture2D ScrollButtonLeftDisabled;
        Texture2D ScrollButtonRight;
        Texture2D ScrollButtonRightDisabled;
        int ScrollButtonHovered = -1;

        int first_visible;

        public HighscoreScreen()
        {
            TransitionOnTime = TimeSpan.FromSeconds(1.5);
            TransitionOffTime = TimeSpan.FromSeconds(0.5);

            AvatarCache = new Dictionary<int, Texture2D>();

            inputExit = new InputAction(
                new Buttons[] { Buttons.B, Buttons.Back },
                new Keys[] { Keys.Escape },
                true);
            scrollUp = new InputAction(
                new Buttons[] { Buttons.LeftThumbstickUp, Buttons.RightThumbstickUp },
                new Keys[] { Keys.Up },
                false
                );
            scrollDown = new InputAction(
                new Buttons[] { Buttons.LeftThumbstickDown, Buttons.RightThumbstickDown },
                new Keys[] { Keys.Down },
                false
                );

            InputEvent.KeyDown += new KeyEventHandler(InputEvent_KeyDown);
        }

        void InputEvent_KeyDown(object sender, KeyEventArgs e)
        {
            Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
            int length = Data.Length;
            bool scrollNeeded = length * 40 > viewport.Height - 200;
            int items_per_screen = (viewport.Height - 200) / 40;

            if (scrollNeeded)
            {
                switch (e.KeyCode)
                {
                    case Keys.Down:
                        first_visible++;
                        break;
                    case Keys.Up:
                        first_visible--;
                        break;
                    case Keys.Home:
                        first_visible = 0;
                        break;
                    case Keys.End:
                        first_visible = Data.Length - 1;
                        break;
                    case Keys.PageDown:
                        first_visible += items_per_screen;
                        break;
                    case Keys.PageUp:
                        first_visible -= items_per_screen;
                        break;
                }

            }
            if (first_visible >= Data.Length)
                first_visible = Data.Length - 1;
            if (first_visible < 0)
                first_visible = 0;

            int current_map_index = Array.IndexOf(Maps, chosenMap);
            switch (e.KeyCode)
            {
                case Keys.Left:
                    {
                        if (current_map_index > 0)
                        {
                            chosenMap = Maps[current_map_index - 1];
                            FetchData();
                        }
                        break;
                    }
                case Keys.Right:
                    {
                        if (current_map_index < Maps.Length - 1)
                        {
                            chosenMap = Maps[current_map_index + 1];
                            FetchData();
                        }
                        break;
                    }
            }
        }

        public override void Activate(bool instancePreserved)
        {
            if (!instancePreserved)
            {
                if (content == null)
                    content = new ContentManager(ScreenManager.Game.Services, "Content");

                font = content.Load<SpriteFont>("SegoeUIMono");
                smallfont = content.Load<SpriteFont>("Smallfont");
                backgroundTexture = content.Load<Texture2D>("Menu\\background");
                backgroundLayer = new Texture2D(ScreenManager.Game.GraphicsDevice, 1, 1);
                backgroundLayer.SetData<Color>(new Color[] { new Color(0, 0, 20, 200) });

                ScrollButtonLeft = content.Load<Texture2D>("Menu\\scroll_left");
                ScrollButtonLeftDisabled = content.Load<Texture2D>("Menu\\scroll_left_grey");
                ScrollButtonRight = content.Load<Texture2D>("Menu\\scroll_right");
                ScrollButtonRightDisabled = content.Load<Texture2D>("Menu\\scroll_right_grey");

                AllData = Highscore.getHighscore();
                Maps = (from entry in AllData
                        orderby entry.highscore_data
                        where entry.highscore_data.StartsWith("map:") &&
                                !entry.highscore_data.StartsWith("map:Testmap")
                        select entry.highscore_data.Replace("map:", "")).Distinct().ToArray();
                chosenMap = Maps[0];
                FetchData();

                foreach (HighscoreEntry entry in AllData)
                {
                    if (!AvatarCache.ContainsKey(entry.user_id) && entry.user_avatar_mini != "")
                    {
                        HttpWebRequest request;
                        try
                        {
                            request = (HttpWebRequest)WebRequest.Create("http://files.pokefans.net/user/avatare/" + entry.user_avatar_mini);
                            System.IO.Stream s = request.GetResponse().GetResponseStream();
                            System.IO.MemoryStream m = new System.IO.MemoryStream();
                            s.CopyTo(m);

                            Texture2D avatar = Texture2D.FromStream(ScreenManager.GraphicsDevice, m);
                            AvatarCache[entry.user_id] = avatar;
                        }
                        catch
                        {

                        }
                    }
                }

                first_visible = 0;

                ScreenManager.Game.ResetElapsedTime();
            }
        }

        public override void Unload()
        {
            content.Unload();
        }

        public override void HandleInput(GameTime gameTime, InputState input)
        {
            if (input == null)
                throw new ArgumentNullException("input");

            KeyboardState keyboardState = input.CurrentKeyboardState;
            GamePadState gamePadState = input.CurrentGamePadState;
            MouseState mouseState = input.CurrentMouseState;

            if (inputExit.Evaluate(input))
                ExitScreen();

            Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
            Rectangle fullscreen = new Rectangle(0, 0, viewport.Width, viewport.Height);

            int length = Data.Length;
            bool scrollNeeded = length * 40 > viewport.Height - 200;

            if (!scrollNeeded)
                first_visible = 0;
            else
            {
                int scrollDiff = mouseState.ScrollWheelValue - input.LastMouseState.ScrollWheelValue;
                if (scrollDiff > 0)
                    first_visible--;
                if (scrollDiff < 0)
                    first_visible++;

                if (first_visible >= Data.Length)
                    first_visible = Data.Length - 1;
                if (first_visible < 0)
                    first_visible = 0;
            }

            int current_map_index = Array.IndexOf(Maps, chosenMap);
            if (new Rectangle(40, 55, 20, 20).Contains(mouseState.X, mouseState.Y))
            {
                ScrollButtonHovered = 0;
                if (input.IsLeftClick() && current_map_index > 0)
                {
                    chosenMap = Maps[current_map_index - 1];
                    FetchData();
                }
            }
            else if (new Rectangle(viewport.Width - 60, 55, 20, 20).Contains(mouseState.X, mouseState.Y))
            {
                ScrollButtonHovered = 1;
                if (input.IsLeftClick() && current_map_index < Maps.Length - 1)
                {
                    chosenMap = Maps[current_map_index + 1];
                    FetchData();
                }
            }
            else
            {
                ScrollButtonHovered = -1;
            }
        }

        public override void Update(GameTime gameTime, bool otherScreenHasFocus,
                                                   bool coveredByOtherScreen)
        {
            base.Update(gameTime, otherScreenHasFocus, false);

            if (IsActive)
            {
                GraphicsDevice graphics = ScreenManager.GraphicsDevice;
                MouseState state = Mouse.GetState();
            }
        }

        public override void Draw(GameTime gameTime)
        {
            // This game has a blue background. Why? Because!
            ScreenManager.GraphicsDevice.Clear(ClearOptions.Target,
                                               Color.CornflowerBlue, 0, 0);

            SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
            spriteBatch.Begin();

            Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
            Rectangle fullscreen = new Rectangle(0, 0, viewport.Width, viewport.Height);
            spriteBatch.Draw(backgroundTexture, fullscreen,
                             new Color(TransitionAlpha, TransitionAlpha, TransitionAlpha));
            spriteBatch.Draw(backgroundLayer, new Rectangle(20, 50, viewport.Width - 40, viewport.Height - 160),
                             Color.White);

            int current_map_index = Array.IndexOf(Maps, chosenMap);
            if (current_map_index > 0)
                spriteBatch.Draw(ScrollButtonHovered == 0 ? ScrollButtonLeftDisabled : ScrollButtonLeft,
                                 new Rectangle(40, 55, 20, 20), Color.White);
            if (current_map_index < Maps.Length - 1)
                spriteBatch.Draw(ScrollButtonHovered == 1 ? ScrollButtonRightDisabled : ScrollButtonRight,
                                 new Rectangle(viewport.Width - 60, 55, 20, 20), Color.White);
            int w = (int)font.MeasureString("Karte: " + chosenMap.Replace("map:", "")).X;
            spriteBatch.DrawString(font, "Karte: " + chosenMap.Replace("map:", ""), new Vector2(viewport.Width / 2 - w / 2, 55), Color.White);

            int y = 100;
            int i = first_visible > 0 ? first_visible : 0;
            while (y < viewport.Height - 100 && i < Data.Length)
            {
                HighscoreEntry entry = Data[i];
                string name = entry.highscore_guestname;
                if (entry.user_id > 1)
                    name = entry.username;
                else
                    name += " (Gast)";

                spriteBatch.DrawString(font, (i + 1).ToString() + ".", new Vector2(40, y), Color.White);
                spriteBatch.DrawString(font, entry.highscore_score.ToString(), new Vector2(75, y), Color.White);
                spriteBatch.DrawString(font, name, new Vector2(200, y), GetColor(entry.user_colour));
                if (AvatarCache.ContainsKey(entry.user_id))
                    spriteBatch.Draw(AvatarCache[entry.user_id], new Vector2(165, y - 9), Color.White);
                spriteBatch.DrawString(font, GetTime(entry.highscore_log_time), new Vector2(500, y), Color.White);

                y += 40;
                i++;
            }

            spriteBatch.End();
        }

        Color GetColor(string c)
        {
            if (c == "") c = "666666";
            int color;
            if (!int.TryParse(c, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.CurrentCulture, out color))
                return Color.White;

            return new Color(color >> 16, (color >> 8) & 0xff, color & 0xff);
        }

        string GetTime(int time)
        {
            DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0);
            dateTime = dateTime.AddSeconds(time);
            return dateTime.ToShortDateString() + ", " + dateTime.ToShortTimeString();
        }

        void FetchData()
        {
            Data = (from entry in AllData
                    orderby entry.highscore_score descending
                    where entry.highscore_data != null && entry.highscore_data == "map:" + chosenMap
                    select entry).ToArray();
        }
    }
}
